﻿using Qy.Core;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Qy.Scenario;

[AppService]
public class ContentService : QyRepository<Content>
{
    private readonly ApplicationContext _applicationContext;
    private readonly ConfigService _configService;
    private readonly string cacheKey;
    private readonly string cacheListKey;
    public ContentService(ApplicationContext applicationContext, ConfigService configService) : base(applicationContext)
    {
        _applicationContext = applicationContext;
        cacheKey = GetEntityFullName();
        cacheListKey = cacheKey + "_list";
        _configService = configService;
    }

    /// <summary>
    /// 编辑一条信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<EditContentAndContent> GetEditAsync(int? id)
    {
        return await Queryable()
               .LeftJoin<ContentContent>((content, contentcontent) => content.Id == contentcontent.Aid)
               .Where(content => content.Id == id)
               .Select((content, contentcontent) => new EditContentAndContent()
               {
                   Id = content.Id.SelectAll(),
                   Content = contentcontent.Content.SelectAll(),
               })
               .FirstAsync(content => content.Id == id);
    }

    public virtual async Task<int> InsertContentAndDataAsync(Content content, ContentContent contentData)
    {
        if (!string.IsNullOrEmpty(content.Img))
            content.Imgbl = 1;
        int pkId = await InsertReturnIdAsync(content);
        if (pkId > 0)
        {
            contentData.Aid = pkId;
            await Context.Insertable(contentData).IgnoreColumns(true).ExecuteCommandAsync();
            return pkId;
        }
        else return 0;
    }

    public virtual async Task<int> UpdateContentAndDataAsync(Content content, ContentContent contentData)
    {
        if (content != null)
        {
            Content getContent = await GetByIdAsync(content.Id);
            contentData.Aid = content.Id;

            getContent.Title = content.Title;
            getContent.Status = content.Status;
            getContent.Img = content.Img;
            getContent.Imgbl = string.IsNullOrEmpty(content.Img) ? 0 : 1;
            getContent.Cid = content.Cid;
            getContent.AttA = content.AttA;
            getContent.AttB = content.AttB;
            getContent.AttC = content.AttC;
            getContent.Examine = content.Examine;
            getContent.Attments = content.Attments;
            int insertKey = await UpdateAsync(getContent);
            int aid = await Context.Storageable(contentData).ExecuteCommandAsync(); //存在更新 不存在插入 (默认是主键)     
            if (insertKey > 0 && aid > 0)
            {
                await _applicationContext.ICacheManager.RemoveAsync(cacheKey + content.Id);
                return insertKey;
            }
            else return 0;
        }
        else return 0;
    }

    public virtual async Task<int> UpdateContentAttAsync(ContentFormChange formChange)
    {
        var exp = Expressionable.Create<Content>();
        exp = exp.AndIF(formChange.Name == "Status", content => content.Status == formChange.Val);
        exp = exp.AndIF(formChange.Name == "AttA", content => content.AttA == formChange.Val);
        exp = exp.AndIF(formChange.Name == "AttB", content => content.AttB == formChange.Val);
        exp = exp.AndIF(formChange.Name == "AttC", content => content.AttC == formChange.Val);

        return await Context.Updateable<Content>()
                 .SetColumns(exp.ToExpression())
                 .Where(content => content.Id == formChange.Id)
                 .ExecuteCommandAsync();
    }
    /// <summary>
    /// 删除一条信息
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public virtual async Task<int> DelContentAndContentAsync(int id)
    {
        if (await DeleteAsync(id) > 0)
        {
            await Context.Deleteable<ContentContent>(id).ExecuteCommandAsync();
            await _applicationContext.ICacheManager.RemoveAsync(cacheKey + id);
            return 1;
        }
        return 0;
    }
    /// <summary>
    /// 按CID获取全部列表  前台
    /// </summary>
    /// <returns></returns>
    public async Task<PagedInfo<ViewContentAndCate>> GetListByCidAsync(int cid, ContentQuery contentQuery)
    {
        contentQuery.Cids = new int[] { cid };
        contentQuery.Limit = contentQuery.PageSize;
        contentQuery.Status = true;
        contentQuery.Uids = new() { -1 };
        return await GetListAynsc(contentQuery);
    }
    /// <summary>
    /// 查询列表
    /// </summary>
    public async Task<PagedInfo<ViewContentAndCate>> GetListAynsc(ContentQuery parm)
    {
        var exp = Expressionable.Create<Content>();
        exp = exp.AndIF(parm.Status, content => content.Status == true);
        exp = exp.AndIF(parm.Cids != null, content => parm.Cids.Contains(content.Cid));
        if (parm.Uids == null)
            exp = exp.And(content => content.Uid == parm.Uid);
        if (parm.Uids != null)
            exp = exp.AndIF(!parm.Uids.Exists(x => x == -1), content => parm.Uids.Contains(content.Uid));
        return await Queryable()
            .LeftJoin<ContentCate>((content, cate) => content.Cid == cate.Id)
            .LeftJoin<User>((content, cate, user) => content.Uid == user.Id)
            .LeftJoin<UserDept>((content, cate, user, dept) => user.DeptId == dept.Id)
            .Where(exp.ToExpression())
            .WhereIF(!string.IsNullOrEmpty(parm.Title), (content, cate) => content.Title.Contains(parm.Title))
            .OrderBy((content) => content.Id, OrderByType.Desc)
            .Select((content, cate, user, dept) => new ViewContentAndCate()
            {
                DeptName = dept.Name,
                CateName = cate.Name
            }, true)
            .ToPageAsync(parm);
    }

    /// <summary>
    /// 搜索列表 前台
    /// </summary>
    public async Task<PagedInfo<ViewContentAndCate>> ContentSearchPageList(ContentQuery parm)
    {
        return await Queryable()
            .LeftJoin<ContentCate>((conetnt, cate) => conetnt.Cid == cate.Id)
            .Where(conetnt => conetnt.Status == true)
            .WhereIF(!string.IsNullOrEmpty(parm.KeyWord), (conetnt, cate) => conetnt.Title.Contains(parm.KeyWord))
            .OrderBy((conetnt) => conetnt.Id, OrderByType.Desc)
            .Select((conetnt, cate) => new ViewContentAndCate()
            {
                CateName = cate.Name
            }, true)
            .ToPageAsync(parm);
    }

    /// <summary>
    /// 前台根据ID联合查询一条，并写入浏览量
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public async Task<ViewContentAndContent> GetOneAsync(int id)
    {
        ViewContentAndContent content = new();
        CacheConfig config = await _configService.GetByCacheConfigAsync();
        if (config.CmsCache)
        {
            content = await _applicationContext.ICacheManager.GetAsync<ViewContentAndContent>(cacheKey + id);
            if (content == null)
            {
                content = await GetOneContentAsync(id);
                await _applicationContext.ICacheManager.SetAsync(cacheKey + id, content, TimeSpan.FromSeconds(config.CmsCacheTime));
            }
        }
        else
        {
            content = await GetOneContentAsync(id);
        }
        await Context.Updateable<Content>()
             .SetColumns(content => content.Hits == content.Hits + 1)
             .Where(content => content.Id == id)
             .ExecuteCommandAsync();//更新浏览数
        return content;
    }
    public async Task<ViewContentAndContent> GetOneContentAsync(int id)
    {
        return await Queryable()
                 .LeftJoin<User>((content, user) => content.Uid == user.Id)
                 .LeftJoin<UserDept>((content, user, dept) => user.DeptId == dept.Id)
                 .LeftJoin<ContentContent>((content, user, dept, contentData) => content.Id == contentData.Aid)
                 .Where(content => content.Id == id && content.Status)
                 .Select((content, user, dept, contentData) => new ViewContentAndContent()
                 {
                     NickName = user.NickName,
                     Id=content.Id,
                     Cid=content.Cid,
                     Time=content.Time,
                     Attments=content.Attments,
                     Title=content.Title,
                     Img = content.Img,
                     Hits = content.Hits,
                     Examine=content.Examine,
                     Aid= contentData.Aid,
                     Content=contentData.Content,
                     DeptName=dept.Name
                 })
                 .FirstAsync(content => content.Id == id);
    }
    /// <summary>
    /// 按CID获取指定条数列表 前台
    /// </summary>
    /// <returns></returns>
    public async Task<List<ViewContentAndCate>> QyList(ContentQuery contentQuery)
    {
        CacheConfig config = await _configService.GetByCacheConfigAsync();
        if (!config.CmsCache || contentQuery.CacheTime == 0)
            return await GetListByLimt(contentQuery);
        string cacheName = contentQuery.CacheName ?? contentQuery.Cids + contentQuery.Limit.ToString() + contentQuery.Att.ToString();
        List<ViewContentAndCate> content = await _applicationContext.ICacheManager.GetAsync<List<ViewContentAndCate>>(cacheListKey + cacheName);
        if (content == null)
        {
            content = await GetListByLimt(contentQuery);
            await _applicationContext.ICacheManager.SetAsync(cacheListKey + cacheName, content, TimeSpan.FromSeconds(contentQuery.CacheTime ?? config.CmsCacheTime));//缓存
        }
        return content;
    }

    /// <summary>
    /// 获取文章及栏目列表条数列表 前台使用
    /// </summary>
    public async Task<List<ViewContentAndCate>> GetListByLimt(ContentQuery parm)
    {
        var exp = Expressionable.Create<Content>();
        exp = exp.AndIF(parm.Status, content => content.Status == parm.Status);
        exp = exp.AndIF(parm.Cids != null, content => parm.Cids.Contains(content.Cid));
        exp = exp.AndIF(parm.Att == 1, content => content.AttA == true);
        exp = exp.AndIF(parm.Att == 2, content => content.AttB == true);
        exp = exp.AndIF(parm.Att == 3, content => content.AttC == true);
        exp = exp.AndIF(parm.ImgBl == true, content => content.Imgbl == 1);

        return await Context.Queryable<Content>()
            .LeftJoin<ContentCate>((content, cate) => content.Cid == cate.Id)
            .Where(exp.ToExpression())
            .WhereIF(!string.IsNullOrEmpty(parm.Title), (content, cate) => content.Title.Contains(parm.Title))
            .OrderBy((content) => content.Id, OrderByType.Desc)
            .Take(parm.Limit)
            .Select((content, cate) => new ViewContentAndCate()
            {
                CateName = cate.Name
            }, true)
            .ToListAsync();

    }


}
